/*
 *  Copyright (C) 2004 Cidero, Inc.
 *
 *  Permission is hereby granted to any person obtaining a copy of 
 *  this software to use, copy, modify, merge, publish, and distribute
 *  the software for any non-commercial purpose, subject to the
 *  following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY IN CONNECTION WITH THE SOFTWARE.
 * 
 *  File: $RCSfile: MediaRendererBridge.java,v $
 *
 */

package com.cidero.bridge;

import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;

import org.cybergarage.upnp.Device;
import org.cybergarage.upnp.device.InvalidDescriptionException;
import org.cybergarage.upnp.device.NotifyListener;
import org.cybergarage.upnp.event.EventListener;
import org.cybergarage.upnp.ssdp.SSDPPacket;

import com.cidero.upnp.AVTransport;
import com.cidero.upnp.ConnectionManager;
import com.cidero.upnp.RenderingControl;
import com.cidero.util.AppPreferences;
import com.cidero.util.MrUtil;


/**
 * Base class for UPnP bridges for non-UPnP-compliant media renderer
 * devices (most commonly music playback devices that support HTTP-GET) 
 */
public abstract class MediaRendererBridge
                extends Device 
//                implements NotifyListener, EventListener
{
  private static Logger logger = Logger.getLogger("com.cidero.bridge");


  //  HTTP Proxy server that sits inbetween the device and the UPNP MediaServer
  //  A single HTTP server is shared by all instances of this class
  static HTTPProxyServer httpServer;
  static int httpServerPort;   // configurable via property file

  String ipAddr = "UnknownIPAddr";

  static AppPreferences pref;

  /**
   * Constructor
   *
   * @param     description file name
   *
   * @exception InvalidDescriptionException if there is an error parsing
   *            the UPnP XML device description
   */
  public MediaRendererBridge( String descriptionFileName,
                                  String ipAddr, String friendlyName )
    throws InvalidDescriptionException
  {
    //
    // Invoke constructor of UPNP device superclass. This parses the XML
    // device and service descriptions, and builds in-memory representations
    //
    super( MrUtil.getResourceAsFile( descriptionFileName ) );

    this.ipAddr = ipAddr;
    setFriendlyName( friendlyName );

    //
    // CLink assigns a random UUID derived from the current system time.
    // We want the UUID for a given device to be repeatable from run-to-run
    // so control points will recognize it as the same device if it is 
    // shut down and restarted.  TODO: Still need to support multiple
    // instances of this proxy somehow (temporarily hardcoded)
    //
    String uuid = friendlyName + "_UUID";
    logger.fine(" Setting UUID to: " + uuid );
    setUUID( uuid );
    updateUDN();

    setNMPRMode( true );
    setWirelessMode( true );

    loadPreferences();

    // Start HTTP server if this is the first bridge device instantiated
    if( httpServer == null )
    {
      try 
      {
        // Constructor starts server up on separate thread
        httpServer = new HTTPProxyServer( this, httpServerPort );
      }
      catch( IOException e )
      {
        logger.fine("Exception creating HTTP server: " + e );
        System.exit(-1);
      }
    }
    
    logger.fine("Leaving MediaRendererBridge base class constructor " );
  }

  /**
   *  Load Bridge preferences. Preference information comes from 
   *  2 sources - the default set of preferences that come with the program,
   *  and the (optional) user-specific set stored in the user's home
   *  directory. The default set is located in the Java classpath under 
   *  the 'properties' subdirectory. The user-specific set is stored 
   *  in the user's home directory, under the '.cidero' subdirectory 
   */
  public static void loadPreferences()
  {
    // Load shared & user-specific preferences for this application
    pref = new AppPreferences(".cidero");

    if( ! pref.load( "Bridge", "MediaRendererBridge" ) )
    {
      logger.severe("Missing preferences file - exiting");
      System.exit(-1);
    }

    // Default server port is 8081
    httpServerPort = pref.getInt("httpServerPort", 8081);
    logger.info("HTTP server port: " + httpServerPort );

    logger.fine("Leaving loadPreference " );
  }


  // Get the device-specific instances of the UPnP services
  abstract public RenderingControl getRenderingControl();
  abstract public AVTransport getAVTransport();
  abstract public ConnectionManager getConnectionManager();

  // Set of actions needed by playback session (need for version of
  // of these actions that doesn't go via UPnP pathway)
  abstract public void avTransportSetTransportURI( String uri ) 
    throws MediaRendererException;
  abstract public void avTransportPlay( String speed )
    throws MediaRendererException;
  abstract public void avTransportPause()
    throws MediaRendererException;
  abstract public void avTransportStop()
    throws MediaRendererException;


  /** 
   * Set/Get the IP address of the underlying non-UPnP device
   */
  public void setIPAddr( String ipAddr )
  {
    this.ipAddr = ipAddr;
  }
  public String getIPAddr()
  {
    return ipAddr;
  }

  /**
   *  Get the pathname portion of the proxy URL for underlying device.
   *  This is the URL the device will use to do HTTP-GET's from the 
   *  UPnP bridge's HTTP server
   *
   *  Examples:
   *
   *     "/UPnPBridge/device/Prismiq-1"
   *     "/UPnPBridge/shoutcast/Homecast1"
   */
  abstract public String getProxyUrlPath();

}

